﻿using MN.Framework.MetaData;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.Objects;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Serialization;
using System.Xml.XPath;


namespace MN.Framework.Common
{
    public static partial class ContextExtensions
    {
        public static string GetTableName<T>(this BaseContext context) where T : class
        {
            //ObjectContext objectContext = ((IObjectContextAdapter)context).ObjectContext;

            return context.GetTableName<T>();
        }

        public static string GetTableName<T>(this ObjectContext context) where T : class
        {
            string sql = context.CreateObjectSet<T>().ToTraceString();
            Regex regex = new Regex("FROM (?<table>.*) AS");
            Match match = regex.Match(sql);

            string table = match.Groups["table"].Value;
            return table;
        }

        public static IEnumerable<object> AsEnumerable(this DbSet set)
        {
            foreach (var entity in set)
                yield return entity;
        }

        public static IEnumerable<object> RelationEntity<EntityType>(this DbContext context, string ForiengKeyField) where EntityType : class
        {
            var t = typeof(EntityType);
            AssociatedWithAttribute[] attrs = (AssociatedWithAttribute[])Attribute.GetCustomAttributes(t, typeof(AssociatedWithAttribute));
            foreach (var attr in attrs)
            {
                if (attr.ForiengKeyField.Equals(ForiengKeyField, StringComparison.CurrentCultureIgnoreCase))
                {
                    var type = attr.ReferencedEntityType;
                    return context.Set(type).AsEnumerable();
                }
            }
            return null;
        }
        public static IEnumerable<object> RelationEntity(this DbContext context, Type EntityType, string ForiengKeyField)
        {
            AssociatedWithAttribute[] attrs = (AssociatedWithAttribute[])Attribute.GetCustomAttributes(EntityType, typeof(AssociatedWithAttribute));
            foreach (var attr in attrs)
            {
                if (attr.ForiengKeyField.Equals(ForiengKeyField, StringComparison.CurrentCultureIgnoreCase))
                {
                    var type = attr.ReferencedEntityType;
                    return context.Set(type).AsEnumerable();
                }
            }
            return null;
        }
        public static Type RelationEntityType<EntityType>(this DbContext context, string ForiengKeyField) where EntityType : class
        {
            var t = typeof(EntityType);
            AssociatedWithAttribute[] attrs = (AssociatedWithAttribute[])Attribute.GetCustomAttributes(t, typeof(AssociatedWithAttribute));
            foreach (var attr in attrs)
            {
                if (attr.ForiengKeyField.Equals(ForiengKeyField, StringComparison.CurrentCultureIgnoreCase))
                {
                    var type = attr.ReferencedEntityType;
                    return type;
                }
            }
            return null;
        }

        public static XmlDocument GetEntityXmlData<T>(this BaseContext Context) where T : BaseEntity
        {
            XmlAttributeOverrides overrides = new XmlAttributeOverrides();
            XmlAttributes attr = new XmlAttributes();
            attr.XmlRoot = new XmlRootAttribute("TheRootElementName");
            overrides.Add(typeof(List<T>), attr);

            XmlDocument xmlDoc = new XmlDocument();
            XPathNavigator nav = xmlDoc.CreateNavigator();
            using (XmlWriter writer = nav.AppendChild())
            {
                XmlSerializer ser = new XmlSerializer(typeof(List<T>), overrides);
                List<T> parameters = Context.Set<T>().ToList();
                ser.Serialize(writer, parameters);
            }
            return xmlDoc;
        }

    }
}
